我們已經知道伺服器是如何接收指令並執行,不過我們還不清楚客戶端要如何將指令發送到伺服器執行玩家的操作。不過因為 ActionScript 在目前 Flash 已經幾乎無法使用的情況下,即使深入了解 ActionScript 也不會對實際開發遊戲有太大的幫助,因此這篇以及後面跟 ActionScript 相關的討論會用一些其他的語言交互討論來相互對照。
首先是 ActionScript 跟 JavaScript 不太一樣的地方是 ActionScript 有像是 Socket 這類套件可以使用,這是因為 ActionScript 是需要跑在對應的 VM 上,而不是直接透過瀏覽器作來執行因此會需要安裝 Flash Player 來運行,所以一些瀏覽器上的限制就不會受到影響。
一樣我們先來觀察連線的實作部分,在 app/client
目錄中的 src/net/ULSocket.as
裡面 Unlight 基於 Socket
物件 做了擴充,並且增加了一些關於 Socket 連線的額外處理,增加的部分主要是關於連線傳輸時的加密。不同於網站有 HTTPS 機制可以使用只需要增加對應的設定,使用 TCP 連線的遊戲是需要自己實作對應的加密或者套用套件來保護資料的傳輸。
接下來繼續用 AuthServer
作為例子,我們可以在 src/net/server/AuthServer.as
找到關於登入伺服器的相關行為定義,假設玩家想要註冊的話,需要呼叫 AuthServer 的 regist
這個指令。
private function regist():void
{
_salt = srp.genSalt();
host.sendCommand(_command.csOpenSocialRegister(player.name,_salt,srp.getVerifire(player.name,player.pass,_salt),SERVER_SB));
}
先跳過 regist
是 private
的問題(Unlight 在某些情況會透過事件的方式呼叫,而不是直接呼叫),我們先看 host.sendCommand()
這個方法,在客戶端要對伺服器發送一個指令會透過 sendCommand
方法來將某個指令的內容傳輸出去。
那麼 host
是什麼呢?我們可以在 AuthServer
所繼承的 Server
物件裡面找到,他會在這些 Server 類型物件初始化的時候被定義,而 Host 物則來自於 src/net/Host.as
裡面的行為大多是在處理像是斷線重試等等的機制。
不過這邊我們先來看 sendCommand
方法做了哪些事情:
/**
* サーバにコマンドを送信
* @para data 送信内容
*/
public function sendCommand(data:ByteArray):void
{
// log.writeLog(log.LV_INFO, "Host.as", "sendCommand: ",data);
_heartBeatTimer.reset();
if (Unlight.live)
{
_socket.send(data);
}
_heartBeatTimer.start();
}
簡單來說,我們在每個伺服器透過 _command
物件產生的指令會變轉換成 Byte Array 然後透過 Host 的 sendCommand
方法將指令往伺服器發送出去,此外這邊還會順便做一些檢查,不過到我們只能確定 Unlight 會透過客戶端生成一些封包資料,然後向伺服器發送還不知道這些資料是怎麼生成的。
另外那麼這邊看到的 _socket
又是什麼呢?
還記得文章一開始提到的 ULSocket
物件嗎?在 Host 初始化之後,每個 Server 會再對 Host 物件設定一些伺服器相關的設定值,然後在需要使用到該伺服器的時候才呼叫 connect()
方法連上伺服器。
例如玩家沒有打開對戰介面,那麼就不要連上對戰伺服器去佔用資源跟可用的連線數。不過隨著硬體跟軟體的技術發展,目前單台伺服器的上限都已經大到一般情況不太需要作分流。
我們再回來看一下 ULSocket 的連線部分,前面有提到像是 _address
這類都是在 Server 初始化後呼叫設定上去的,當設定完畢後會接著呼叫 connect()
連上伺服器。
// アドレスとポートとコマンドを初期化
public function init(a:String, p:uint, c:Command):void
{
_address = a;
if (p == 0)
{
log.writeLog(log.LV_WARN, this,"Port number is 0.");
}
_port = p;Kyoto Steak
cmd = c;
}
/**
* 通信の開始
*/
public function connect():void
{
sessionKey =null;
log.writeLog(log.LV_DEBUG, this," Connect Start",_address,_port);
_socket.connect(_address, _port);
closed = false;
}
如此一來我們就將 Flash 的客戶端跟伺服器連接起來,後續就可以進行發送各種指令的行為。
我的個人部落格是弦而時習之平常會把自己發現的一些新技巧紀錄在上面,也歡迎大家來逛逛。